﻿#ifndef QTSOCKET_TCPSESSION_H
#define QTSOCKET_TCPSESSION_H

#include "qnet_global.h"
#include <QHostAddress>
#include <QPointer>
class QTcpSocket;

QNET_NAMESPACE_BEGIN

class NetReading;
class NetWriting;

/**
 * @brief The TcpSession class 表示tcp会话。
 */
class QNETSHARED_EXPORT TcpSession : public QObject
{
    Q_OBJECT
public:
    explicit TcpSession(QObject *parent = Q_NULLPTR);
    TcpSession(QTcpSocket *socket, QObject *parent = Q_NULLPTR);
    virtual ~TcpSession() override;

    /**
     * @brief proc 处理写入。（异步）
     * @param writing 写入实例。
     * @return 成功加入写入队列返回true。
     */
    bool write(QSharedPointer<NetWriting> writing);
    /**
     * @brief close 关闭连接。
     */
    void close();
    /**
     * @brief localIp 获取本地IP。
     * @return
     */
    QHostAddress localIp() const;
    /**
     * @brief remoteIp 获取远端IP。
     * @return
     */
    QHostAddress remoteIp() const;

    /**
     * @brief localPort 获取本地端口。
     * @return
     */
    quint16 localPort() const;

    /**
     * @brief remotePort 获取远端端口。
     * @return
     */
    quint16 remotePort() const;

    /**
     * @brief reading 获取tcp数据读取实例。
     * @return
     */
    NetReading *reading() const;

    /**
     * @brief reading 设置数据读取实例。
     */
    void setReading(NetReading *reading);

    /**
     * @brief bManualClosed 获取是否手动释放。
     * @return
     */
    bool bManualClosed() const;

private:
signals:
    /**
     * @brief stateChanged 状态改变信号。
     * @param state
     */
    void stateChanged(QAbstractSocket::SocketState state);
    /**
     * @brief disconnected 失去连接信号。
     */
    void disconnected();
    /**
     * @brief error 错误信息。
     */
    void error(QAbstractSocket::SocketError);
    /**
     * @brief connected 连接完毕。
     */
    void connected();
    /**
     * @brief onClose 会话关闭信号。
     */
    void onClose();
private slots:
    /**
     * @brief readyRead 准备写入槽。
     */
    void readyRead();
    /**
     * @brief writeSlot 写入槽
     * @param writing 写入。
     */
    void writeSlot(QSharedPointer<NetWriting> writing);

    /**
     * @brief closeSlot 关闭session。
     */
    void closeSlot();
private:
signals:
    /**
     * @brief write 写入信号。
     * @param writing
     */
    void writeSignal(QSharedPointer<NetWriting> writing);
private:
    NetReading *m_reading;
    QTcpSocket *m_socket;
    bool m_bManualClosed; // 是否手动关闭。
};
/**
 * @brief The ISessionListener class 会话监视接口。
 */
class QNETSHARED_EXPORT ISessionListener
{
public:
    virtual ~ISessionListener();
    /**
     * @brief onStateChanged 会话状态改变。
     * @param session 会话。
     * @param connected 状态是否链接，false表示断开。
     */
    virtual void onStateChanged(TcpSession *session, bool connected) = 0;
    /**
     * @brief onError 错误信息。
     */
    virtual void onError(QAbstractSocket::SocketError) = 0 ;
};
QNET_NAMESPACE_END

#endif // TCPSESSION_H
